#
# Copyright (C) [2024] Xingyun Integrated Circuit, Inc.
#
# GreenCode was a private technology asset of Xingyun Integrated Circuit， Inc （Confidential）
# Author: Shawn.Tan
# Date: 2025.10.28
#
# History: Initial Version 2025.10.28
#
#
from gpgpu.EnvGPGPU import EnvGPGPU
from gpgpu.GenThreadGPGPU import GenThreadGPGPU
from base.Sequence import Sequence
from base.InstructionMap import InstructionMap
from base.TestUtils import assert_equal, assert_false
from DV.gpgpu.trees.instruction_tree import *


class MainSequence(Sequence):
    """Generate a sequence of instructions that are randomly selected from
    the specified subset of CALM instructions.
    1 specify the number of instructions to be generated by setting
        instruction_count
    2 specify a the desired subset by setting the instruction_group.  Some
        of the predefined instruction subsets are listed below with the
        statement for all but one commented out. Just uncomment the subset
        you wish to use, while commenting out the others.  For more details
        on the specific instructions in each subset and a list of the other
        available predefined subsets, see
        force/py/DV/gpgpu/trees/instruction_tree.py.
    3 if you want to a specific instruction, set the_instruction2 to the
    appropriate string and use the_instruction2 in the genInstruction call.
    """

    def generate(self, **kargs):

        # 1 - set the number of instructions to generate
        instruction_count = 5

        # 2 - Choose the subset of GPGPU instruction you wish to use
        instruction_group = (
            LDST32_All_instructions
            if self.getGlobalState("AppRegisterWidth") == 32
            else LDST_All_instructions
        )

        # 3 - If you want to specify a specific instruction, set
        # the_instruction2 to the appropriate string here and replace the
        # argument in the genInstruction call to the_instruction2.  For
        # the string values to use for a given instruction, search for that
        # instruction in force/py/DV/gpgpu/trees/instruction_tree.py.
        # the_instruction2 = "ADD##CALM"

        for i in range(10):

            # defaults to request size of 1 byte of memory
            vm_address = self.genVA(Size=2 ** (i + 4), Align=2 ** (i + 4))
            self.notice(">>>>>>>>>>>>>>>>>  vm_address:        {:12X}".format(vm_address))

            the_instruction = self.pickWeighted(instruction_group)
            record_id = self.genInstruction(the_instruction, {"LSTarget": vm_address})
            instruction_info = self.queryInstructionRecord(record_id)
            chosen_instruction = instruction_info["Name"]

            self.notice(">>>>>>>>>>>>>  Chosen instruction: {}".format(chosen_instruction))

            self.notice(">>>>>>>>>>>>>  vm_address:    {:012X}".format(vm_address))
            self.notice(
                ">>>>>>>>>>>>>  LS_Target:     {:012X}".format(instruction_info["LSTarget"])
            )

            # Self-checking
            # The if conditions are othogonal
            if chosen_instruction in LDST_Byte_instructions:
                target_size = 1
            elif chosen_instruction in LDST_Half_instructions:
                target_size = 2
            elif chosen_instruction in LDST_Word_instructions:
                target_size = 4
            elif chosen_instruction in LDST_Double_instructions:
                target_size = 8
            else:
                self.error("Unexpected instruction chosen:  {}".format(chosen_instruction))

            # Checking - based on the instruction target size, 1, 2, 4 or 8
            # bytes should be set to not free. Other bytes should be set to
            # free.  Assert on any mismatches.

            is_address_free = self.verifyVirtualAddress(vm_address, 4, False)
            is_address_plus01_free = self.verifyVirtualAddress(vm_address + 1, 4, False)
            is_address_plus02_free = self.verifyVirtualAddress(vm_address + 2, 4, False)
            is_address_plus03_free = self.verifyVirtualAddress(vm_address + 3, 4, False)
            is_address_plus04_free = self.verifyVirtualAddress(vm_address + 4, 4, False)
            is_address_plus05_free = self.verifyVirtualAddress(vm_address + 5, 4, False)
            is_address_plus06_free = self.verifyVirtualAddress(vm_address + 6, 4, False)
            is_address_plus07_free = self.verifyVirtualAddress(vm_address + 7, 4, False)
            is_address_plus08_free = self.verifyVirtualAddress(vm_address + 8, 4, False)
            is_address_plus16_free = self.verifyVirtualAddress(vm_address + 16, 4, False)

            # Dump info to the gen.log
            self.notice(">>>>>>>>>>>>>  The address is free:     {}".format(is_address_free))
            self.notice(
                ">>>>>>>>>>>>>  The address+01 is free:  {}".format(is_address_plus01_free)
            )
            self.notice(
                ">>>>>>>>>>>>>  The address+02 is free:  {}".format(is_address_plus02_free)
            )
            self.notice(
                ">>>>>>>>>>>>>  The address+03 is free:  {}".format(is_address_plus03_free)
            )
            self.notice(
                ">>>>>>>>>>>>>  The address+04 is free:  {}".format(is_address_plus04_free)
            )
            self.notice(
                ">>>>>>>>>>>>>  The address+05 is free:  {}".format(is_address_plus05_free)
            )
            self.notice(
                ">>>>>>>>>>>>>  The address+05 is free:  {}".format(is_address_plus06_free)
            )
            self.notice(
                ">>>>>>>>>>>>>  The address+05 is free:  {}".format(is_address_plus07_free)
            )
            self.notice(
                ">>>>>>>>>>>>>  The address+08 is free:  {}".format(is_address_plus08_free)
            )
            self.notice(
                ">>>>>>>>>>>>>  The address+16 is free:  {}".format(is_address_plus16_free)
            )

            # Checking target address should always be reserved.  Additional
            # bytes should be reserved based on the target_size.
            if target_size == 1:
                assert_equal(
                    is_address_free,
                    False,
                    "Byte of memory not reserved that should have been.",
                )
                assert_equal(
                    is_address_plus01_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus02_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus03_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus04_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus05_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus06_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus07_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus08_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus16_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )

            if target_size == 2:
                assert_equal(
                    is_address_free,
                    False,
                    "Byte of memory not reserved that should have been.",
                )
                assert_equal(
                    is_address_plus01_free,
                    False,
                    "Byte of memory not reserved that should have been.",
                )
                assert_equal(
                    is_address_plus02_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus03_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus04_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus05_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus06_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus07_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus08_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus16_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )

            if target_size == 4:
                assert_false(is_address_free)
                assert_equal(
                    is_address_plus01_free,
                    False,
                    "Byte of memory not reserved that should have been.",
                )
                assert_equal(
                    is_address_plus02_free,
                    False,
                    "Byte of memory not reserved that should have been.",
                )
                assert_equal(
                    is_address_plus03_free,
                    False,
                    "Byte of memory not reserved that should have been.",
                )
                assert_equal(
                    is_address_plus04_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus05_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus06_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus07_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus08_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus16_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )

            if target_size == 8:
                assert_equal(
                    is_address_free,
                    False,
                    "Byte of memory not reserved that should have been.",
                )
                assert_equal(
                    is_address_plus01_free,
                    False,
                    "Byte of memory not reserved that should have been.",
                )
                assert_equal(
                    is_address_plus02_free,
                    False,
                    "Byte of memory not reserved that should have been.",
                )
                assert_equal(
                    is_address_plus03_free,
                    False,
                    "Byte of memory not reserved that should have been.",
                )
                assert_equal(
                    is_address_plus04_free,
                    False,
                    "Byte of memory not reserved that should have been.",
                )
                assert_equal(
                    is_address_plus05_free,
                    False,
                    "Byte of memory not reserved that should have been.",
                )
                assert_equal(
                    is_address_plus06_free,
                    False,
                    "Byte of memory not reserved that should have been.",
                )
                assert_equal(
                    is_address_plus07_free,
                    False,
                    "Byte of memory not reserved that should have been.",
                )
                assert_equal(
                    is_address_plus08_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )
                assert_equal(
                    is_address_plus16_free,
                    True,
                    "Unexpected byte of memory was reserved.",
                )


# Points to the MainSequence defined in this file
MainSequenceClass = MainSequence

# Using GenThreadGPGPU by default, can be overriden with extended classes
GenThreadClass = GenThreadGPGPU

# Using EnvGPGPU by default, can be overriden with extended classes
EnvClass = EnvGPGPU
